#include "fuLogger.h"
#include "BoostForeach.h"

#include <fstream>
#include <iostream>
#include <sstream>  // std::ostringstream
#include <iomanip>  // std::setw

BEGIN_NAMESPACE_CPPX

struct fuLogger::pimpl_t
{
	std::auto_ptr<std::ostream>	ostream_ptr;
	bool owner_managed;

	pimpl_t(std::ostream * os, bool owner) :
	ostream_ptr(os),owner_managed(owner){
	}
	~pimpl_t(void){
		if( !owner_managed )
			ostream_ptr.release();
	}
};

fuLogger::fuLogger( void ) :
pimpl_ptr(new pimpl_t(&std::cout,false))
{
    *(pimpl_ptr->ostream_ptr) << "----- Begin of Logging system output to std::cout -----" << std::endl;
}

fuLogger::fuLogger( const std::string & out_filename ) :
pimpl_ptr(new pimpl_t(new std::ofstream(out_filename.c_str()),true))
{
    *(pimpl_ptr->ostream_ptr) << "----- Begin of Logging system output to std::ofstream -----" << std::endl;
}

fuLogger::fuLogger( std::ostream * out_stream, bool ower_manage ) :
pimpl_ptr(new pimpl_t(out_stream,ower_manage))
{
    *(pimpl_ptr->ostream_ptr) << "----- Begin of Logging system output to std::ostream -----" << std::endl;
}

fuLogger::~fuLogger( void )
{
	*(pimpl_ptr->ostream_ptr) << "----- End of Logging system output   -----" << std::endl;
}

fuLogger & fuLogger::operator<<(const fuError & err)
{
    *(pimpl_ptr->ostream_ptr) << "Error : " << err._error;
    return *this;
}

fuLogger & fuLogger::operator<<(const fuEnter & enter)
{
	*(pimpl_ptr->ostream_ptr) << std::endl;
	return *this;
}

fuLogger & fuLogger::operator<<(const std::vector<char> & dat)
{
    bool delimiter = false;
    foreach(char ch,dat){
        if( delimiter )
            *(pimpl_ptr->ostream_ptr) << ":";
        else
            delimiter = true;

        std::ostringstream oss;
        oss << std::hex
            << std::uppercase
            << std::setw(2)
            << std::setfill('0')
            << (unsigned int)(unsigned char)ch;
        *(pimpl_ptr->ostream_ptr) << oss.str();
    }
    return *this;
}

fuLogger & fuLogger::operator<<(const std::string & str)
{
    *(pimpl_ptr->ostream_ptr) << str;
    return *this;
}

fuLogger & fuLogger::operator<<(const char * str)
{
    *(pimpl_ptr->ostream_ptr) << str;
    return *this;
}

fuLogger & fuLogger::operator<<( int num )
{
	*(pimpl_ptr->ostream_ptr) << num;
	return *this;
}

fuLogger & fuLogger::operator<<( unsigned int num )
{
    *(pimpl_ptr->ostream_ptr) << num;
    return *this;
}

fuLogger & fuLogger::operator<<( float num )
{
    *(pimpl_ptr->ostream_ptr) << num;
    return *this;
}

fuLogger & fuLogger::operator<<( double num )
{
    *(pimpl_ptr->ostream_ptr) << num;
    return *this;
}

std::ostream & fuLogger::get_ostream( void )
{
	return *pimpl_ptr->ostream_ptr;
}

//////////////////////////////////////////////////////////////////////////
fuLogger * fuLoggerPtr( void )
{
	return fuLogger::getInstance();
}

fuLogger & fuLoggerRef( void )
{
	return *fuLoggerPtr();
}

END_NAMESPACE_CPPX
